package com.gitee.kamismile.stone.rpc.core.proxy.imp.jdk;

import com.gitee.kamismile.stone.rpc.api.invocation.support.StoneInvocation;
import com.gitee.kamismile.stone.rpc.api.invocation.support.StoneInvocationFactory;
import com.gitee.kamismile.stone.rpc.common.invocation.StoneInvocationType;
import com.gitee.kamismile.stone.rpc.common.support.StoneURL;
import com.gitee.kamismile.stone.rpc.core.invocation.StoneInvokeInvoker;
import  org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;

public class JDKInvocationHandler implements InvocationHandler {

    protected static final Logger logger = LoggerFactory.getLogger(JDKInvocationHandler.class);

    private StoneInvokeInvoker stoneInvokeInvoker;

    public JDKInvocationHandler(StoneInvokeInvoker stoneInvokeInvoker) {
        this.stoneInvokeInvoker = stoneInvokeInvoker;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

//        checkValid();

        StoneInvocation invocation = StoneInvocationFactory.createInvocation(stoneInvokeInvoker.getMapperInterface(), method, stoneInvokeInvoker.getStoneURL(), StoneInvocationType.PRODUCER);


        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invocation, args);
        }
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes.length == 0) {
            if ("toString".equals(methodName)) {
                return invocation.toString();
            } else if ("hashCode".equals(methodName)) {
                return invocation.hashCode();
            }
        } else if (parameterTypes.length == 1 && "equals".equals(methodName)) {
            return invocation.equals(args[0]);
        }

        StoneURL stoneURL = invocation.getStoneURL();
        stoneURL.setMethodName(methodName);
        stoneURL.setParameterTypes(parameterTypes);
        stoneURL.setArguments(args);

        invocation.setServerName(stoneInvokeInvoker.getServerName());
        invocation.setServerVersion(stoneInvokeInvoker.getServerVersion());
        invocation.setTimeout(stoneInvokeInvoker.getTimeout());
        if (CompletableFuture.class.equals(method.getReturnType())) {
            return stoneInvokeInvoker.completableFutureInvoke(invocation);
        }

        return stoneInvokeInvoker.syncInvoke(invocation);
    }
}
